import { _decorator, Collider, Component, instantiate, macro, math, Node, Prefab, Vec3, Label, Animation } from 'cc';
import { Bullet } from '../bullet/Bullet';
import { Constant } from './Constant';
import { EnemyPlane } from '../plane/EnemyPlane';
import { BulletProp } from '../bullet/BulletProp';
import { SelfPlane } from '../plane/SelfPlane';
import { AudioManager } from './AudioManager';
import { PoolManager } from './PoolManager';
const { ccclass, property } = _decorator;

@ccclass('GameManager')
export class GameManager extends Component {

    @property(SelfPlane)
    private playPlane: SelfPlane = null;

    @property(Prefab)
    private bullet01: Prefab = null;
    @property(Prefab)
    private bullet02: Prefab = null;
    @property(Prefab)
    private bullet03: Prefab = null;
    @property(Prefab)
    private bullet04: Prefab = null;
    @property(Prefab)
    private bullet05: Prefab = null;

    @property(Prefab)
    private bulletPropH: Prefab = null;

    @property(Prefab)
    private bulletPropM: Prefab = null;

    @property(Prefab)
    private bulletPropS: Prefab = null;

    private bulletPropSpeed = 0.3;

    private bulletType = Constant.BulletPropType.BULLET_M;

    @property(Node)
    private bulletRoot: Node;


    //enemy
    @property(Prefab)
    private enemy01: Prefab = null;

    @property(Prefab)
    private enemy02: Prefab = null;

    @property(Node)
    private gamePage: Node = null;

    @property(Node)
    private gameOverPage: Node = null;

    @property(Label)
    private gameScore: Label = null;

    @property(Label)
    private gameOverScore: Label = null;

    @property(Animation)
    private overAnim: Animation = null;

    @property(AudioManager)
    private audioManager: AudioManager = null;

    @property(Prefab)
    private enemyExplorePrefab: Prefab = null;


    private createEnemyTime = 1;

    private enemy1Speed = 0.5;
    private enemy2Speed = 0.7;

    @property
    private shootTime = 0.3;

    @property
    private bulletSpeed = 1;

    private currentShootTime = 0;
    private isShootingFlag = false;

    private currentCreateEnemyTime = 0;
    private _combinationInterval = Constant.Combination.PLANE1;

    public isgameStart = false;

    private _score = 0;

    start() {
        this.currentShootTime = this.shootTime;
        this._combinationInterval = Constant.Combination.PLANE1;
        // this.changePlaneMode();
    }

    update(deltaTime: number) {
        if (!this.isgameStart) {
            return;
        }
        if (this.playPlane.isDie) {
            this.gameOver();
            return;
        }

        //  发射子弹
        this.currentShootTime += deltaTime;
        if (this.isShootingFlag && this.currentShootTime > this.shootTime) {
            if (this.bulletType === Constant.BulletPropType.BULLET_H) {
                this.createPlayerBulletH();
            } else if (this.bulletType === Constant.BulletPropType.BULLET_S) {
                this.createPlayerBulletS();
            } else {
                this.createPlayerBulletM();
            }
            //子弹音频
            const name = "bullet" + (this.bulletType % 2 + 1);
            this.playAudioEffect(name);
            this.currentShootTime = 0
        }

        //enemy
        this.currentCreateEnemyTime += deltaTime;
        if (this._combinationInterval === Constant.Combination.PLANE1) {
            if (this.currentCreateEnemyTime > this.createEnemyTime) {
                this.createEnemyPlane()
                this.currentCreateEnemyTime = 0;
            }
        } else if (this._combinationInterval === Constant.Combination.PLANE2) {
            if (this.currentCreateEnemyTime > this.createEnemyTime * 0.9) {
                const randomCombination = math.randomRangeInt(1, 3);
                if (randomCombination === Constant.Combination.PLANE2) {
                    this.createCombination1();
                } else {
                    this.createEnemyPlane()
                }
                this.currentCreateEnemyTime = 0;
            }
        } else {
            if (this.currentCreateEnemyTime > this.createEnemyTime * 0.8) {
                const randomCombination = math.randomRangeInt(1, 4);

                if (randomCombination === Constant.Combination.PLANE3) {
                    this.createCombination2();
                } else if (randomCombination === Constant.Combination.PLANE2) {
                    this.createCombination1();
                } else {
                    this.createEnemyPlane()
                }
                this.currentCreateEnemyTime = 0;
            }
        }
    }


    public restart() {
        this.isgameStart = true;
        this.currentShootTime = 0;
        this.isShootingFlag = false;
        this.currentCreateEnemyTime = 0;
        this._combinationInterval = Constant.Combination.PLANE1;
        this.bulletType = Constant.BulletPropType.BULLET_M;
        this.playPlane.node.setPosition(0, 0, 15);
        this.playPlane.init();
        this._score = 0;
        this.gameScore.string = this._score.toString();
        this.changePlaneMode();
    }

    public returnMain() {
        this.currentShootTime = 0;
        this.isShootingFlag = false;
        this.currentCreateEnemyTime = 0;
        this._combinationInterval = Constant.Combination.PLANE1;
        this.bulletType = Constant.BulletPropType.BULLET_M;
        this.playPlane.node.setPosition(0, 0, 15);
        this._score = 0;
        this.unschedule(this.modeChange);
    }

    public gameStart() {
        this.restart();
    }

    public gameOver() {
        this.isgameStart = false;
        this.gamePage.active = false;
        this.gameOverPage.active = true;
        this.gameOverScore.string = this._score.toString();
        this.overAnim.play();
        this.isShootingFlag = false;

        this.unschedule(this.modeChange);
        this._destroyAll();
    }

    public addScore() {
        this._score++;
        this.gameScore.string = this._score.toString();
    }

    private createPlayerBulletM() {
        const bullet = PoolManager.instance().get(this.bullet01, this.bulletRoot);
        // bullet.setParent(this.bulletRoot);
        const pos = this.playPlane.node.position;

        bullet.setPosition(pos.x, pos.y, pos.z - 7);
        const bulletComp = bullet.getComponent(Bullet);
        bulletComp.show(this.bulletSpeed, false);

        const colliderComp = bullet.getComponent(Collider);
        colliderComp.setGroup(Constant.ColliderType.SELF_BULLET);
        colliderComp.setMask(Constant.ColliderType.ENEMY_PLANE);

    }
    private createPlayerBulletH() {
        const pos = this.playPlane.node.position;

        const bulletL = PoolManager.instance().get(this.bullet03, this.bulletRoot);
        // bulletL.setParent(this.bulletRoot);

        bulletL.setPosition(pos.x - 2.5, pos.y, pos.z - 7);
        const bulletLComp = bulletL.getComponent(Bullet);
        bulletLComp.show(this.bulletSpeed, false);

        const colliderLComp = bulletL.getComponent(Collider);
        colliderLComp.setGroup(Constant.ColliderType.SELF_BULLET);
        colliderLComp.setMask(Constant.ColliderType.ENEMY_PLANE);



        const bulletR = PoolManager.instance().get(this.bullet03, this.bulletRoot);
        // bulletR.setParent(this.bulletRoot);

        bulletR.setPosition(pos.x + 2.5, pos.y, pos.z - 7);
        const bulletRComp = bulletR.getComponent(Bullet);
        bulletRComp.show(this.bulletSpeed, false);

        const colliderRComp = bulletR.getComponent(Collider);
        colliderRComp.setGroup(Constant.ColliderType.SELF_BULLET);
        colliderRComp.setMask(Constant.ColliderType.ENEMY_PLANE);

    }
    private createPlayerBulletS() {

        const pos = this.playPlane.node.position;

        const bulletL = PoolManager.instance().get(this.bullet05, this.bulletRoot);
        // bulletL.setParent(this.bulletRoot);

        bulletL.setPosition(pos.x - 4, pos.y, pos.z - 7);
        const bulletLComp = bulletL.getComponent(Bullet);
        bulletLComp.show(this.bulletSpeed, false, Constant.Direction.LEFT);

        const colliderLComp = bulletL.getComponent(Collider);
        colliderLComp.setGroup(Constant.ColliderType.SELF_BULLET);
        colliderLComp.setMask(Constant.ColliderType.ENEMY_PLANE);



        const bulletM = PoolManager.instance().get(this.bullet05, this.bulletRoot);
        // bulletM.setParent(this.bulletRoot);

        bulletM.setPosition(pos.x, pos.y, pos.z - 7);
        const bulletMComp = bulletM.getComponent(Bullet);
        bulletMComp.show(this.bulletSpeed, false);

        const colliderMComp = bulletM.getComponent(Collider);
        colliderMComp.setGroup(Constant.ColliderType.SELF_BULLET);
        colliderMComp.setMask(Constant.ColliderType.ENEMY_PLANE);


        const bulletR = PoolManager.instance().get(this.bullet05, this.bulletRoot);
        // bulletR.setParent(this.bulletRoot);

        bulletR.setPosition(pos.x + 4, pos.y, pos.z - 7);
        const bulletRComp = bulletR.getComponent(Bullet);
        bulletRComp.show(this.bulletSpeed, false, Constant.Direction.RIGHT);

        const colliderRComp = bulletR.getComponent(Collider);
        colliderRComp.setGroup(Constant.ColliderType.SELF_BULLET);
        colliderRComp.setMask(Constant.ColliderType.ENEMY_PLANE);
    }

    public createEnemyBullet(targetPos: Vec3) {
        const bullet = PoolManager.instance().get(this.bullet02, this.bulletRoot);
        // bullet.setParent(this.bulletRoot);

        bullet.setPosition(targetPos.x, targetPos.y, targetPos.z + 6);
        const bulletComp = bullet.getComponent(Bullet);
        bulletComp.show(1, true);

        const colliderComp = bullet.getComponent(Collider);
        colliderComp.setGroup(Constant.ColliderType.ENEMY_BULLET);
        colliderComp.setMask(Constant.ColliderType.SELF_PLANE);
    }

    private createEnemyPlane() {
        const whichEnemy = math.randomRangeInt(1, 3);
        let prefab: Prefab = null;
        let speed = 0;
        if (whichEnemy === Constant.EnemyType.TYPE1) {
            prefab = this.enemy01;
            speed = this.enemy1Speed;
        }
        if (whichEnemy === Constant.EnemyType.TYPE2) {
            prefab = this.enemy02;
            speed = this.enemy2Speed;
        }

        const enemy = PoolManager.instance().get(prefab, this.node);
        // enemy.setParent(this.node);
        const enemyComp = enemy.getComponent(EnemyPlane);
        enemyComp.setSpeed(this, speed, true);

        const randomPos = math.randomRangeInt(-25, 26)
        enemy.setPosition(randomPos, 0, -50);
    }

    private createCombination1() {
        const enemys = new Array<Node>(5);
        for (let i = 0; i < enemys.length; i++) {
            enemys[i] = PoolManager.instance().get(this.enemy01, this.node);
            const enemy = enemys[i];
            // enemy.setParent(this.node);
            const enemyComp = enemy.getComponent(EnemyPlane);
            enemyComp.setSpeed(this, this.enemy1Speed, false);

            enemy.setPosition(-20 + i * 10, 0, -50);
        }
    }

    private createCombination2() {
        const enemys = new Array<Node>(7);
        const combinationPos = [
            -21, 0, -60,
            -14, 0, -55,
            -7, 0, -50,
            0, 0, -45,
            7, 0, -50,
            14, 0, -55,
            21, 0, -60,
        ];
        for (let i = 0; i < enemys.length; i++) {
            enemys[i] = PoolManager.instance().get(this.enemy02, this.node);
            const enemy = enemys[i];
            // enemy.setParent(this.node);
            const enemyComp = enemy.getComponent(EnemyPlane);
            enemyComp.setSpeed(this, this.enemy2Speed, false);
            const startIndex = i * 3
            enemy.setPosition(combinationPos[startIndex], combinationPos[startIndex + 1], combinationPos[startIndex + 2]);
        }
    }

    public createEnemyExplore(pos: Vec3) {
        const enemyExplore = PoolManager.instance().get(this.enemyExplorePrefab, this.node);
        enemyExplore.setPosition(pos);
    }

    public playAudioEffect(name: string) {
        this.audioManager.play(name);
    }

    public changeBulletType(type: number) {
        this.bulletType = type;
    }

    public isShooting(value: boolean) {
        this.isShootingFlag = value;
    }

    private changePlaneMode() {
        this.schedule(this.modeChange, 10, macro.REPEAT_FOREVER);
    }

    private modeChange() {
        this._combinationInterval++;

        //生成道具
        this.createBulletProp()
    }

    private createBulletProp() {
        const randomPos = math.randomRangeInt(1, 4);
        let prefab: Prefab = null;
        if (randomPos === Constant.BulletPropType.BULLET_H) {
            prefab = this.bulletPropH;
        } else if (randomPos === Constant.BulletPropType.BULLET_M) {
            prefab = this.bulletPropM;
        } else if (randomPos === Constant.BulletPropType.BULLET_S) {
            prefab = this.bulletPropS;
        }
        const prop = PoolManager.instance().get(prefab, this.node);
        // prop.setParent(this.node);
        prop.setPosition(20, 0, -50);
        const propComp = prop.getComponent(BulletProp);
        propComp.show(this, this.bulletPropSpeed);
    }

    private _destroyAll() {
        //todo 删除所有子节点

        this.node.removeAllChildren();

        this.bulletRoot.removeAllChildren();
    }
}

